home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianSliders.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
45KB
|
1,594 lines
/* ScianSliders.c
routines for slider-type controls
Jim Lyons
4/3/91 original version
5/29/91 EMP removed lib headers
8/12/91 modified to use ScianFontSystem calls
8/16/91 modified to use Get/Set2DIntBounds
9/5/91 added help
9/27/91 added active/inactive stuff
10/7/91 removed blind-typing from keydown routine
10/23/91 fixed exception end-point labeling of scales
5/20/92 EMP changed ENTERMETHOD to CHANGEDVALUE for slider readout
5/22/92 EMP changed slider readout to use ParseReal
5/31/92 EMP fixed / 0 bug in scroll bars
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianFontSystem.h"
#include "ScianArrays.h"
#include "ScianStyle.h"
#include "ScianColors.h"
#include "ScianIDs.h"
#include "ScianHelp.h"
#include "ScianErrors.h"
#include "ScianControls.h"
#include "ScianWindows.h"
#include "ScianObjWindows.h"
#include "ScianEvents.h"
#include "ScianScripts.h"
#include "ScianMethods.h"
#include "ScianDraw.h"
#include "ScianSliders.h"
#include "ScianScales.h"
#include "ScianTextBoxes.h"
#include "ScianSymbols.h"
#define SB_GAP 4
#define MAXNUMWID 37 /*** maximum allowed width of number on scale ***/
/* bit definitions for highlight of scrollbar parts */
#define THUMBHL 0x01
#define INCRHL 0x02
#define DECRHL 0x04
/* repeat time for scroll bar buttons */
#define DELAY 0.2
/* EMP static method declarations, NOT prototypes */
static ObjPtr DrawSlider();
static ObjPtr TrackSlider();
static ObjPtr GetVal();
static ObjPtr SetVal();
static ObjPtr SliderKeyProc();
static ObjPtr MakeHelpString();
ObjPtr sliderClass;
void InitSliders()
{
sliderClass = NewObject(controlClass, 0);
AddToReferenceList(sliderClass);
SetVar(sliderClass, NAME, NewString("Slider"));
SetMethod(sliderClass, DRAW, DrawSlider);
SetMethod(sliderClass, PRESS, TrackSlider);
SetMethod(sliderClass, SETVAL, SetVal);
SetMethod(sliderClass, GETVAL, GetVal);
SetMethod(sliderClass, KEYDOWN, SliderKeyProc);
SetMethod(sliderClass, MAKE1HELPSTRING, MakeHelpString);
}
void KillSliders()
{
DeleteThing(sliderClass);
}
#ifdef PROTO
ObjPtr NewSlider(int left, int right, int bottom, int top, int style, char *name)
#else
ObjPtr NewSlider(left, right, bottom, top, style, name)
int left, right, bottom, top, style;
char *name;
#endif
{
ObjPtr newSlider;
if (left > right)
{
register int n;
n = left; left = right; right = n;
}
if (bottom > top)
{
register int n;
n = bottom; bottom = top; top = n;
}
newSlider = NewObject(sliderClass, 0);
Set2DIntBounds(newSlider, left, right, bottom, top);
/* set up defaults for slider parameters */
SetVar(newSlider, STYLE, NewInt(style));
SetVar(newSlider, NAME, NewString(name));
SetVar(newSlider, HIGHLIGHTED, NewInt(false));
SetVar(newSlider, LOVALUE, NewReal(0.0));
SetVar(newSlider, HIVALUE, NewReal(1.0));
SetVar(newSlider, STEPVALUE, NewReal(0.1));
SetVar(newSlider, VALUE, NewReal(0.0));
SetVar(newSlider, TRACKNOT, NewInt(false));
SetVar(newSlider, KEYSTRING, NewString("\0"));
SetVar(newSlider, READOUT, NULLOBJ);
SetVar(newSlider, TYPESTRING, NewString("slider"));
SetVar(newSlider, ACTIVATED, ObjTrue);
switch (style)
{
case SCALE:
case REVSCALE:
SetVar(newSlider, BIGSTEP, NewReal(0.5));
SetVar(newSlider, LILSTEP, NewReal(0.1));
SetVar(newSlider, ANCHOR, NewReal(0.0));
SetVar(newSlider, FORMAT, NewString("%3.1f"));
break;
default:
SetVar(newSlider, STYLE, NewInt(PLAIN));
break;
}
return newSlider;
}
#ifdef PROTO
ObjPtr NewScrollbar(int left, int right, int bottom, int top, char *name)
#else
ObjPtr NewScrollbar(left, right, bottom, top, name)
int left, right, bottom, top;
char *name;
#endif
{
ObjPtr newScrollbar;
if (left > right)
{
register int n;
n = left; left = right; right = n;
}
if (bottom > top)
{
register int n;
n = bottom; bottom = top; top = n;
}
newScrollbar = NewObject(sliderClass, 0);
Set2DIntBounds(newScrollbar, left, right, bottom, top);
/* set up defaults for scrollbar parameters */
SetVar(newScrollbar, STYLE, NewInt(SCROLL));
SetVar(newScrollbar, NAME, NewString(name));
SetVar(newScrollbar, HIGHLIGHTED, NewInt(0x00)); /* see bit defns */
SetVar(newScrollbar, LOVALUE, NewReal(0.0));
SetVar(newScrollbar, HIVALUE, NewReal(1.0));
SetVar(newScrollbar, STEPVALUE, NewReal(0.1));
SetVar(newScrollbar, VALUE, NewReal(0.0));
SetVar(newScrollbar, PORTIONSHOWN, NewReal(1.0));
SetVar(newScrollbar, TRACKNOT, NewInt(false));
SetVar(newScrollbar, KEYSTRING, NewString("\0"));
SetVar(newScrollbar, TYPESTRING, NewString("scrollbar"));
SetVar(newScrollbar, ACTIVATED, ObjTrue);
return newScrollbar;
}
static ObjPtr MakeHelpString(theSlider, theClass)
ObjPtr theSlider, theClass;
{
char tempBuf[1000]; /*** fix! ***/
int style = GetInt(GetVar(theSlider, STYLE));
if (style == SCROLL)
strcpy(tempBuf, "To operate the scrollbar, drag the sliding bar with the \
mouse or click in the track to snap it to a new position. Click and hold the arrow \
buttons to scroll automatically. The size of the sliding bar in the control \
relative to the track is proportional to the area being viewed relative to the entire \
scrollable area. If the bar is as long as the track, the entire area is in view and \
the scrollbar does nothing.");
else
{
strcpy(tempBuf, "To operate the slider, drag the pointer \
with the mouse or click in the track to snap it to a new position. After clicking on the \
slider, the arrow keys on the keyboard will also move the pointer. ");
if (style == SCALE || style == REVSCALE)
strcat(tempBuf, "The scale shows the range of values possible \
for this slider. Holding the shift key down while dragging the pointer constrains the \
slider to values on the tic marks of the scale. "); /*** fix! ***/
}
SetVar(theClass, HELPSTRING, NewString(tempBuf));
return ObjTrue;
}
#ifdef PROTO
void ActivateSlider(ObjPtr slider, Bool act)
#else
void ActivateSlider(slider, act)
ObjPtr slider;
Bool act;
#endif
{
ObjPtr readout;
if (act == GetPredicate(slider, ACTIVATED)) return; /* activation state unchanged */
if (act)
{
SetVar(slider, ACTIVATED, ObjTrue);
if ( readout = GetVar(slider, READOUT) ) SetVar(readout, ACTIVATED, ObjTrue);
}
else
{
SetVar(slider, ACTIVATED, ObjFalse);
if (readout = GetVar(slider, READOUT)) SetVar(readout, ACTIVATED, ObjFalse);
if (AmICurrent(slider)) MakeMeCurrent(NULLOBJ);
}
ImInvalid(slider);
}
#ifdef PROTO
void SetTrackNot(ObjPtr theSlider, int value)
#else
void SetTrackNot(theSlider,value)
ObjPtr theSlider;
int value;
#endif
{
SetVar(theSlider, TRACKNOT, NewInt(value));
}
#ifdef PROTO
static void Update(ObjPtr theReadout, real val)
#else
static void Update(theReadout, val)
ObjPtr theReadout;
real val;
#endif
{
if(logging) InhibitLogging(true);
if(theReadout)
{
/*EMP kluge to prevent infinite loop*/
FuncTyp method;
sprintf(tempStr,"%g",val);
method = GetMethod(theReadout, CHANGEDVALUE);
SetMethod(theReadout, CHANGEDVALUE, (FuncTyp) 0);
SetTextBox(theReadout, tempStr);
SetMethod(theReadout, CHANGEDVALUE, method);
}
if(logging) InhibitLogging(false);
}
static ObjPtr EditSlider(readout)
ObjPtr readout;
{
ObjPtr slider;
real val;
if (slider = GetObjectVar("EditSlider", readout, REPOBJ))
{
if (logging) InhibitLogging(true);
strcpy(tempStr, GetString(GetVar(readout, VALUE)));
if (!ParseReal(&val, tempStr)) /* error in input */
{
WarnUser(CW_NUMBERERROR);
return ObjFalse;
}
if (val == missingData)
{
WarnUser(CW_MISSINGERROR);
return ObjFalse;
}
if (val >= plusInf || val <= minusInf)
{
WarnUser(CW_INFINITYERROR);
return ObjFalse;
}
SetSliderValue(slider, val);
if (logging) InhibitLogging(false);
}
return ObjTrue;
}
#ifdef PROTO
ObjPtr SliderReadout(ObjPtr theSlider, ObjPtr theReadout)
#else
ObjPtr SliderReadout(theSlider, theReadout)
ObjPtr theSlider, theReadout;
#endif
{
SetVar(theSlider, READOUT, theReadout);
SetVar(theReadout, REPOBJ, theSlider);
SetMethod(theReadout, CHANGEDVALUE, EditSlider);
Update(theReadout, GetSliderValue(theSlider));
return NULLOBJ;
}
static ObjPtr GetVal(theSlider)
ObjPtr theSlider;
{
return GetVar(theSlider, VALUE);
}
#ifdef PROTO
real GetSliderValue(ObjPtr theSlider)
#else
real GetSliderValue(theSlider)
ObjPtr theSlider;
#endif
{
ObjPtr theVal;
theVal = GetVar(theSlider, VALUE);
if (theVal) return GetReal(theVal);
else return 0;
}
static ObjPtr SetVal(theObj, theVal)
ObjPtr theObj, theVal;
{
if (!theVal) /* special case: value is NULL */
{
SetVar(theObj, VALUE, NULLOBJ);
return ObjTrue;
}
else if (IsReal(theVal)) SetSliderValue(theObj, GetReal(theVal));
else if (IsInt(theVal)) SetSliderValue(theObj, (real) GetInt(theVal));
else return ObjFalse; /* error in argument */
LogControl(theObj);
return ObjTrue;
}
#ifdef PROTO
ObjPtr SetSliderValue(ObjPtr theSlider, real val)
#else
ObjPtr SetSliderValue(theSlider, val)
ObjPtr theSlider;
real val;
#endif
{
ObjPtr theHiV, theLoV, theStepV;
ObjPtr theReadout, theStyle, scale;
real hiVal, loVal, stepVal;
int style;
if ((theHiV = GetVar(theSlider, VALUE)) && val == GetReal(theHiV)) return ObjFalse; /* no change */
/* sanity check */
theHiV = GetRealVar("SetSliderValue", theSlider, HIVALUE);
theLoV = GetRealVar("SetSliderValue", theSlider, LOVALUE);
theStepV = GetRealVar("SetSliderValue", theSlider, STEPVALUE);
theStyle = GetIntVar("SetSliderValue", theSlider, STYLE);
if (!theHiV || !theLoV || !theStepV || !theStyle) return NULLOBJ; /* Yow! Bad. Very bad. */
hiVal = GetReal(theHiV);
loVal = GetReal(theLoV);
stepVal = GetReal(theStepV);
style = GetInt(theStyle);
theReadout = GetVar(theSlider, READOUT);
if ( style != SCROLL && stepVal != 0.0)
{
register int n;
n = 0.5 + val / stepVal;
val = n * stepVal;
}
/* adjust range if value out of it */
if (val > hiVal)
{
SetVar(theSlider, HIVALUE, NewReal(val));
if (scale = GetVar(theSlider, THESCALE)) SetScaleRange(scale, loVal, val);
}
if (val < loVal)
{
SetVar(theSlider, LOVALUE, NewReal(val));
if (scale = GetVar(theSlider, THESCALE)) SetScaleRange(scale, val, hiVal);
}
SetVar(theSlider, VALUE, NewReal(val));
Update(theReadout, val);
if (style == SCALE || style == REVSCALE)
{
int left, right, bottom, top;
Get2DIntBounds(theSlider, &left, &right, &bottom, &top);
if (right - left < top - bottom)
/* vertical orientation */
{
bottom += VSCALEINSET - CTL_WID/2;
top -= VSCALEINSET - CTL_WID/2;
if (style == SCALE)
ImInvalidBounds(theSlider,
left - BIGTICK - 3 - MAXNUMWID, right, bottom, top);
else ImInvalidBounds(theSlider, left,
right + BIGTICK + 3 + MAXNUMWID, bottom, top);
}
else /*horizontal*/
{
left += HSCALEINSET - CTL_WID/2;
right -= HSCALEINSET - CTL_WID/2;
if (style == SCALE)
ImInvalidBounds(theSlider, left, right,
bottom, top + BIGTICK + 3 + SCALEFONTSIZE);
else ImInvalidBounds(theSlider, left, right,
bottom - BIGTICK - 3 - SCALEFONTSIZE, top);
}
}
else
{
ImInvalid(theSlider);
}
/*** KLUDGE so Eric can speed up drawing ***/
{
ObjPtr parent = GetVar(theSlider, PARENT);
if (parent) ImInvalid(parent);
}
ChangedValue(theSlider);
return ObjTrue;
}
#ifdef PROTO
void SetPortionShown(ObjPtr theSlider, real porSh)
#else
void SetPortionShown(theSlider, porSh)
ObjPtr theSlider;
real porSh;
#endif
{
if (porSh < 0.0) porSh = 0.0;
SetVar(theSlider, PORTIONSHOWN, NewReal(porSh));
}
static ObjPtr SliderKeyProc(theSlider, key, flags)
ObjPtr theSlider;
int key;
long flags;
{
#ifdef INTERACTIVE
ObjPtr theHiV, theLoV, theStepV, theVal, theStyle;
real hiV, loV, stepV, val;
int style;
ObjPtr theReadout;
if(!AmICurrent(theSlider)) return ObjFalse; /* keyboard input not for me */
theHiV = GetRealVar("SliderKeyProc", theSlider, HIVALUE);
theLoV = GetRealVar("SliderKeyProc", theSlider, LOVALUE);
theStepV = GetRealVar("SliderKeyProc", theSlider, STEPVALUE);
theVal= GetRealVar("SliderKeyProc", theSlider, VALUE);
theStyle = GetIntVar("SliderKeyProc", theSlider, STYLE);
if (!theHiV || !theLoV || !theStepV || !theVal || !theStyle)
return ObjTrue; /* Yow! Bad, wrong, deep doo-doo */
theReadout = GetVar(theSlider, READOUT);
hiV = GetReal(theHiV);
loV = GetReal(theLoV);
stepV = GetReal(theStepV);
val = GetReal(theVal);
style = GetInt(theStyle);
/* process arrow keys only */
if (key == FK_UP_ARROW || key == FK_RIGHT_ARROW)
{
SaveForUndo(theSlider);
/* increment slider value by stepV */
if (stepV == 0.0) val += (hiV - loV)/100;
else val += stepV;
if (val <= hiV)
{
SetVar(theSlider, VALUE, NewReal(val));
Update(theReadout, val);
ImInvalid(theSlider);
ChangedValue(theSlider);
}
}
else if (key == FK_DOWN_ARROW || key == FK_LEFT_ARROW)
{
SaveForUndo(theSlider);
/* decrement slider value by stepV */
if (stepV == 0.0) val -= (hiV - loV)/100;
else val -= stepV;
if (val >= loV)
{
SetVar(theSlider, VALUE, NewReal(val));
Update(theReadout, val);
ImInvalid(theSlider);
ChangedValue(theSlider);
}
}
else return ObjFalse; /* not one of my keys -- pass it */
#endif
return ObjTrue;
}
#ifdef PROTO
void SetSliderRange(ObjPtr theSlider, real hiVal, real loVal, real stepVal)
#else
void SetSliderRange(theSlider, hiVal, loVal, stepVal)
ObjPtr theSlider;
real hiVal, loVal, stepVal;
#endif
{
ObjPtr theVal,theStyle;
real val;
int style;
theStyle = GetIntVar("SetSliderRange", theSlider, STYLE);
if (!theStyle) return; /* Yow! */
style = GetInt(theStyle);
/* sanity check */
if (hiVal < loVal)
{
real tmp;
tmp = hiVal; hiVal = loVal; loVal = tmp;
}
theVal = GetVar(theSlider, VALUE);
if (theVal)
{
val = GetReal(theVal);
/* adjust range if value if out of range */
if (val < loVal) loVal = val;
if (val > hiVal) hiVal = val;
}
if (stepVal > hiVal - loVal)
stepVal = hiVal - loVal;
else if (style != SCROLL && stepVal != 0.0)
{
int n;
n = ((hiVal - loVal) / stepVal) + 0.5;
hiVal = n * stepVal + loVal;
}
SetVar(theSlider, HIVALUE, NewReal(hiVal));
SetVar(theSlider, LOVALUE, NewReal(loVal));
SetVar(theSlider, STEPVALUE, NewReal(stepVal));
if (style == SCALE || style == REVSCALE)
{
int left, right, bottom, top;
ObjPtr scale;
if (scale = GetVar(theSlider, THESCALE))
{
SetScaleRange(scale, loVal, hiVal);
}
else
{
Get2DIntBounds(theSlider, &left, &right, &bottom, &top);
if (right - left < top - bottom)
/* vertical orientation */
{
bottom += VSCALEINSET - CTL_WID/2;
top -= VSCALEINSET - CTL_WID/2;
if (style == SCALE) ImInvalidBounds(theSlider,
left - BIGTICK - 3 - MAXNUMWID, right, bottom, top);
else ImInvalidBounds(theSlider, left,
right + BIGTICK + 3 + MAXNUMWID, bottom, top);
}
else /*horizontal*/
{
left += HSCALEINSET - CTL_WID/2;
right -= HSCALEINSET - CTL_WID/2;
if (style == SCALE) ImInvalidBounds(theSlider, left,
right, bottom, top + BIGTICK + 3 + SCALEFONTSIZE);
else ImInvalidBounds(theSlider, left, right,
bottom - BIGTICK - 3 - SCALEFONTSIZE, top);
}
}
}
else
{
ImInvalid(theSlider);
}
/*** KLUDGE so Eric can speed up drawing ***/
{
ObjPtr parent = GetVar(theSlider, PARENT);
if (parent) ImInvalid(parent);
}
}
#ifdef PROTO
void SetSliderScale(ObjPtr theSlider, real bigStep, real lilStep, real anchor, char *format)
#else
void SetSliderScale(theSlider, bigStep, lilStep, anchor, format)
ObjPtr theSlider;
real bigStep, lilStep, anchor;
char *format;
#endif
{
SetVar(theSlider, BIGSTEP, NewReal(bigStep));
SetVar(theSlider, LILSTEP, NewReal(lilStep));
SetVar(theSlider, ANCHOR, NewReal(anchor));
SetVar(theSlider, FORMAT, NewString(format));
}
static ObjPtr DrawSlider(theSlider)
ObjPtr theSlider;
{
#ifdef GRAPHICS
int cp,cl,sl;
int wid;
Coord x[3][2];
ObjPtr theHiV, theLoV, theStepV, theVal, theHilite, theStyle, thePorSh;
ObjPtr theBigStep, theLilStep, theAnchor, theFormat;
int left, right, bottom, top, style;
int i, j, nl, nh, m;
int active, highlight;
Bool nullV;
real hiV, loV, stepV, val, porSh, bigStep, lilStep, anchorV, sV, siz, r;
real anchorC, hiC, loC; /* Coordinate of scale hi, lo, and anchor point */
real minC = -1e6, maxC = 0; /*** don't ask... */
char *format, theNumber[10];
Get2DIntBounds(theSlider, &left, &right, &bottom, &top);
/* get the style and value parameters */
theHiV = GetRealVar("DrawSlider", theSlider, HIVALUE);
theLoV = GetRealVar("DrawSlider", theSlider, LOVALUE);
theStepV = GetRealVar("DrawSlider", theSlider, STEPVALUE);
theHilite = GetIntVar("DrawSlider", theSlider, HIGHLIGHTED);
theStyle = GetIntVar("DrawSlider", theSlider, STYLE);
if (!theHiV || !theLoV || !theStepV || !theHilite || !theStyle)
return NULLOBJ; /* Yow! Bad, wrong, doo-doo */
hiV = GetReal(theHiV);
loV = GetReal(theLoV);
stepV = GetReal(theStepV);
if ( theVal = GetVar(theSlider, VALUE) ) val = GetReal(theVal);
highlight = GetInt(theHilite);
active = GetPredicate(theSlider, ACTIVATED);
style = GetInt(theStyle);
switch (style)
{
case PLAIN:
break;
case SCALE:
case REVSCALE:
theBigStep = GetRealVar("DrawSlider", theSlider, BIGSTEP);
theLilStep = GetRealVar("DrawSlider", theSlider, LILSTEP);
theAnchor = GetRealVar("DrawSlider", theSlider, ANCHOR);
theFormat = GetStringVar("DrawSlider", theSlider, FORMAT);
if (!theBigStep || !theLilStep || !theAnchor || !theFormat)
return NULLOBJ; /* Yow! Missing things! */
bigStep = GetReal(theBigStep);
lilStep = GetReal(theLilStep);
anchorV = GetReal(theAnchor);
format = GetString(theFormat);
SetupFont("Helvetica", SCALEFONTSIZE); /***/
break;
case SCROLL:
thePorSh = GetRealVar("DrawSlider", theSlider, PORTIONSHOWN);
if (thePorSh) porSh = GetReal(thePorSh);
else return NULLOBJ; /* Yow! Something's rong */
/* normalize portion shown */
porSh = porSh/(porSh + hiV - loV);
break;
default:
style = PLAIN;
SetVar(theSlider, STYLE, NewInt(PLAIN));
break;
}
/* so draw it already */
if (right - left > top - bottom)
{
/* horizontal orientation */
cl = (bottom + top) / 2;
switch(style)
{
case SCALE:
left += HSCALEINSET - CTL_WID/2;
right -= HSCALEINSET - CTL_WID/2;
if (IsDrawingRestricted(left, right, bottom,
top + BIGTICK + 3 + SCALEFONTSIZE)) return ObjFalse;
DrawSunkenRect(left, right, cl-TRK_WID/2, cl+TRK_WID/2,
active ? UIPGREEN : UIBACKGROUND);
loC = left + CTL_WID/2;
hiC = right - CTL_WID/2;
r = (hiC - loC) / (hiV - loV);
anchorC = loC + r*(anchorV - loV);
sl = top;
if (theVal)
{
cp = loC + r*(val - loV) + 0.5;
DrawCtlUp(cp-CTL_WID/2, cp+CTL_WID/2, bottom, sl-2,
highlight ? UIHIBACKGROUND : UIBACKGROUND);
}
/***/ if (GetVar(theSlider, THESCALE)) break;
/***/ printf("Old style scale on slider %s\n", GetString(GetVar(theSlider, NAME)));
/* draw scale over slider */
SetUIColor(active ? UITEXT : UIGREYTEXT);
DrawLine(loC, sl, hiC, sl);
nl = (loV - anchorV)/bigStep - 1;
nh = (hiV - anchorV)/bigStep + 1;
for (i=nl; i<=nh; ++i)
{
sV = i*bigStep + anchorV; /* starting value for each step */
if (sV >= loV && sV <= hiV)
{
int u = anchorC + r*(sV - anchorV) + 0.5;
DrawLine(u, sl, u, sl + BIGTICK);
/* draw number next to tick */
sprintf(theNumber, format, sV);
DrawAString(CENTERALIGN, u, sl + BIGTICK + 3, theNumber);
/* remember min and max coord of labels */
if (minC < -1e5) minC = u - wid/2;
maxC = u + wid/2;
}
if (i == nh) break;
m = bigStep/lilStep + 0.5;
for (j=1; j<m; ++j)
{
int u = anchorC + r*(sV - anchorV + j*lilStep) + 0.5;
if (u > hiC + 1) break;
if (u >= loC)
{
DrawLine(u, sl, u, sl + LILTICK);
}
}
}
/* check if end points need labels */
sprintf(theNumber, format, loV);
wid = StrWidth(theNumber);
if (loC + wid/2 < minC) /* label low end of scale */
{
DrawAString(CENTERALIGN, loC, sl + BIGTICK + 3, theNumber);
}
sprintf(theNumber, format, hiV);
wid = StrWidth(theNumber);
if (hiC - wid/2 > maxC) /* label high end of scale */
{
DrawAString(CENTERALIGN, hiC, sl + BIGTICK + 3, theNumber);
}
break;
#if 0
case REVSCALE:
left += HSCALEINSET - CTL_WID/2;
right -= HSCALEINSET - CTL_WID/2;
if (IsDrawingRestricted(left, right,
bottom - BIGTICK + 3 + SCALEFONTSIZE, top)) return ObjFalse;
DrawSunkenRect(left, right, cl-TRK_WID/2, cl+TRK_WID/2,
active ? UIPGREEN : UIBACKGROUND);
loC = left + CTL_WID/2;
hiC = right - CTL_WID/2;
r = (hiC - loC) / (hiV - loV);
anchorC = loC + r*(anchorV - loV);
cp = loC + r*(val - loV) + 0.5;
/* draw scale under slider */
sl = bottom;
SetUIColor(active ? UITEXT : UIGREYTEXT);
DrawLine(loC, sl, hiC, sl);
nl = (loV - anchorV)/bigStep - 1;
nh = (hiV - anchorV)/bigStep + 1;
for (i=nl; i<=nh; ++i)
{
sV = i*bigStep + anchorV; /* "starting" value for each step */
if (sV >= loV && sV <= hiV)
{
int u = anchorC + r*(sV - anchorV) + 0.5;
DrawLine(u, sl, u, sl - BIGTICK);
/* draw number next to tick */
sprintf(theNumber, format, sV);
DrawAString(CENTERALIGN, u, sl - BIGTICK - 3, theNumber);
}
if (i == nh) break;
m = bigStep/lilStep + 0.5;
for (j=1; j<m; ++j)
{
int u = anchorC + r*(sV - anchorV + j*lilStep) + 0.5;
if (u > hiC) break;
if (u >= loC)
{
DrawLine(u, sl, u, sl - LILTICK);
}
}
}
DrawCtlDown(cp-CTL_WID/2, cp+CTL_WID/2, sl+2, top,
highlight ? UIHIBACKGROUND : UIBACKGROUND);
break;
#endif
case SCROLL:
if (IsDrawingRestricted(left, right, bottom,
top))
{
return ObjFalse;
}
wid = top - bottom;
loC = left + wid + EDGE + SB_GAP;
hiC = right - wid - EDGE - SB_GAP;
siz = (hiC - loC)*porSh; /* size of thumb */
if (siz < wid) siz = wid; /* min size is square */
hiC -= siz; /* lower limit of posn of thumb */
if (hiV <= loV) sV = loC;
else sV = loC + (val-loV)*(hiC - loC)/(hiV - loV) + 0.5;
/* draw left-button */
DrawRaisedRect(left, left+wid, bottom, top,
DECRHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
/* (draw left arrow on top) */
FillUITri(left + 0.28*wid, cl,
left + 0.61*wid, cl - wid/3,
left + 0.61*wid,cl + wid/3,
active ? UITEXT : UIGREYTEXT);
/* draw right-button */
DrawRaisedRect(right-wid, right, bottom, top,
INCRHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
/* (draw right arrow on top) */
FillUITri(right - 0.28*wid, cl,
right - 0.61*wid, cl - wid/3,
right - 0.61*wid, cl + wid/3,
active ? UITEXT : UIGREYTEXT);
/* draw track */
DrawSunkenRect(left+wid+SB_GAP, right-wid-SB_GAP, bottom, top,
active ? UIPGREEN : UIBACKGROUND);
/* draw thumb */
DrawRaisedRect(sV, sV+siz, bottom+EDGE, top-EDGE,
THUMBHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
break;
case PLAIN:
default:
if (IsDrawingRestricted(left, right, bottom,
top)) return ObjFalse;
DrawSunkenRect(left, right, cl-TRK_WID/2, cl+TRK_WID/2,
active ? UIPGREEN : UIBACKGROUND);
loC = left + CTL_WID/2;
hiC = right - CTL_WID/2;
r = (hiC - loC) / (hiV - loV);
if (theVal)
{
cp = loC + r*(val - loV) + 0.5;
DrawRaisedRect(cp-CTL_WID/2, cp+CTL_WID/2, bottom, top,
highlight ? UIHIBACKGROUND : UIBACKGROUND);
}
break;
}
}
else
{
/* vertical orientation */
cl = (left + right)/2;
switch(style)
{
case SCALE:
bottom += VSCALEINSET - CTL_WID/2;
top -= VSCALEINSET - CTL_WID/2;
if (IsDrawingRestricted(left - BIGTICK - 3 - MAXNUMWID, right,
bottom, top)) return ObjFalse;
DrawSunkenRect(cl - TRK_WID/2, cl + TRK_WID/2, bottom, top,
active ? UIPGREEN : UIBACKGROUND);
loC = bottom + CTL_WID/2;
hiC = top - CTL_WID/2;
r = (hiC - loC)/(hiV - loV);
anchorC = r*(anchorV - loV) + loC;
sl = left;
if (theVal)
{
cp = loC + r*(val-loV) + 0.5;
DrawCtlLeft(sl+2, right, cp-CTL_WID/2, cp+CTL_WID/2,
highlight ? UIHIBACKGROUND : UIBACKGROUND);
}
/***/ if (GetVar(theSlider, THESCALE)) break;
/***/ printf("Old style scale on slider %s\n", GetString(GetVar(theSlider, NAME)));
/* draw scale on left of slider */
SetUIColor(active ? UITEXT : UIGREYTEXT);
DrawLine(sl, loC, sl, hiC);
nl = (loV - anchorV)/bigStep - 1;
nh = (hiV - anchorV)/bigStep + 1;
for (i=nl; i<=nh; ++i)
{
sV = i*bigStep + anchorV; /* starting value for each step */
if (sV >= loV && sV <= hiV)
{
int u = anchorC + r*(sV - anchorV) + 0.5;
DrawLine(sl, u, sl - BIGTICK, u);
/* draw number next to tick */
sprintf(theNumber, format, sV);
DrawAString(RIGHTALIGN, sl - BIGTICK - 3, u - 3, theNumber);
/* remember min and max coords of labels */
if (minC < -1e5) minC = u - 3;
maxC = u - 3 + SCALEFONTSIZE;
}
if (i == nh) break;
m = bigStep/lilStep + 0.5;
for (j=1; j<m; ++j)
{
int u = anchorC + r*(sV - anchorV + j*lilStep) + 0.5;
if (u > hiC + 1) break;
if (u >= loC)
{
DrawLine(sl, u, sl - LILTICK, u);
}
}
}
/* check if end points need labels */
sprintf(theNumber, format, loV);
wid = StrWidth(theNumber);
if (loC - 3 + SCALEFONTSIZE < minC) /* label low end of scale */
{
DrawAString(RIGHTALIGN, sl - BIGTICK - 3, loC - 3, theNumber);
}
if (hiC - 3 > maxC) /* label high end of scale */
{
sprintf(theNumber, format, hiV);
wid = StrWidth(theNumber);
DrawAString(RIGHTALIGN, sl - BIGTICK - 3, hiC - 3, theNumber);
}
break;
#if 0
case REVSCALE:
bottom += VSCALEINSET - CTL_WID/2;
top -= VSCALEINSET - CTL_WID/2;
if (IsDrawingRestricted(left, right + BIGTICK + 3 + MAXNUMWID,
bottom, top)) return ObjFalse;
DrawSunkenRect(cl - TRK_WID/2, cl + TRK_WID/2, bottom, top,
active ? UIPGREEN : UIBACKGROUND);
loC = bottom + CTL_WID/2;
hiC = top - CTL_WID/2;
r = (hiC - loC)/(hiV - loV);
anchorC = r*(anchorV - loV) + loC;
cp = loC + r*(val-loV) + 0.5;
/* draw scale on right of slider */
sl = right;
SetUIColor(active ? UITEXT : UIGREYTEXT);
DrawLine(sl, loC, sl, hiC);
nl = (loV - anchorV)/bigStep - 1;
nh = (hiV - anchorV)/bigStep + 1;
for (i=nl; i<=nh; ++i)
{
sV = i*bigStep + anchorV; /* "starting" value for each step */
if (sV >= loV && sV <= hiV)
{
int u = anchorC + r*(sV - anchorV) + 0.5;
DrawLine(sl, u, sl + BIGTICK, u);
/* draw number next to tick */
sprintf(theNumber, format, sV);
wid = StrWidth(theNumber);
DrawAString(LEFTALIGN, sl + BIGTICK + 3, u - 3, theNumber);
}
if (i == nh) break;
m = bigStep/lilStep + 0.5;
for (j=1; j<m; ++j)
{
int u = anchorC + r*(sV - anchorV + j*lilStep) + 0.5;
if (u > hiC) break;
if (u >= loC)
{
DrawLine(sl, u, sl + LILTICK, u);
}
}
}
DrawCtlRight(left, sl-2, cp-CTL_WID/2, cp+CTL_WID/2,
highlight ? UIHIBACKGROUND : UIBACKGROUND);
break;
#endif
case SCROLL:
if (IsDrawingRestricted(left, right, bottom,
top))
{
return ObjFalse;
}
wid = right - left;
loC = bottom + wid + EDGE + SB_GAP;
hiC = top - wid - EDGE - SB_GAP;
siz = (hiC - loC)*porSh; /* size of thumb */
if (siz < wid) siz = wid; /* min size is square */
hiC -= siz; /* limit position of thumb */
if (hiV == loV) sV = loC;
else sV = loC + (val-loV)*(hiC - loC)/(hiV - loV) + 0.5;
/* draw up-button */
DrawRaisedRect(left, right, top - wid, top,
INCRHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
/* (draw up arrow on top) */
FillUITri(cl, top - 0.28*wid,
cl - wid/3, top - 0.61*wid,
cl + wid/3, top - 0.61*wid,
active ? UITEXT : UIGREYTEXT);
/* draw down-button */
DrawRaisedRect(left, right, bottom, bottom + wid,
DECRHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
/* (draw down arrow on top) */
FillUITri(cl, bottom + 0.28*wid,
cl - wid/3, bottom + 0.61*wid,
cl + wid/3, bottom + 0.61*wid,
active ? UITEXT : UIGREYTEXT);
/* draw track */
DrawSunkenRect(left, right, bottom + wid + SB_GAP, top - wid - SB_GAP,
active ? UIPGREEN : UIBACKGROUND);
/* draw thumb */
DrawRaisedRect(left + EDGE, right - EDGE, sV, sV + siz,
THUMBHL & highlight ? UIHIBACKGROUND : UIBACKGROUND);
break;
case PLAIN:
default:
if (IsDrawingRestricted(left, right, bottom,
top)) return ObjFalse;
DrawSunkenRect(cl - TRK_WID/2, cl + TRK_WID/2, bottom, top,
active ? UIPGREEN : UIBACKGROUND);
loC = bottom + CTL_WID/2;
hiC = top - CTL_WID/2;
r = (hiC - loC)/(hiV - loV);
if (theVal)
{
cp = loC + r*(val-loV) + 0.5;
DrawRaisedRect(left, right, cp-CTL_WID/2, cp+CTL_WID/2,
highlight ? UIHIBACKGROUND : UIBACKGROUND);
}
break;
}
}
if (!active) FillUIGauzeRect(left, right, bottom, top, UIBACKGROUND);
#endif
return NULLOBJ;
}
static ObjPtr TrackSlider(theSlider, mouseX, mouseY, flags)
ObjPtr theSlider;
int mouseX, mouseY;
long flags;
{
#ifdef INTERACTIVE
int left, right, bottom, top, cp;
ObjPtr theHiV, theLoV, theStepV, theLilStep;
int style, mX, mY, offset;
real hiV, loV, stepV, val, curVal, lilStep, valSave;
ObjPtr theStyle, theValue;
ObjPtr theReadout;
struct tms tbuf;
long prevTime = 0L;
Bool hilit = false, tracking;
Get2DIntBounds(theSlider, &left, &right, &bottom, &top);
/* return if mouse outside slider rectangle */
if (mouseX < left - 1 || mouseX > right + 1 || mouseY < bottom -1
|| mouseY > top + 1) return ObjFalse;
if (TOOL(flags) == T_HELP)
{
ContextHelp(theSlider);
return ObjTrue;
}
/* return if not active or has null value */
if (!GetPredicate(theSlider, ACTIVATED)
|| !(theValue = GetVar(theSlider, VALUE))) return ObjTrue;
MakeMeCurrent(theSlider); /* make slider current for keyboard input */
SaveForUndo(theSlider);
/* get range and value of slider */
theHiV = GetRealVar("TrackSlider", theSlider, HIVALUE);
theLoV = GetRealVar("TrackSlider", theSlider, LOVALUE);
theStepV = GetRealVar("TrackSlider", theSlider, STEPVALUE);
theStyle = GetIntVar("TrackSlider", theSlider, STYLE);
if (!theHiV || !theLoV || !theStepV || !theStyle) return ObjTrue; /* Yow! */
hiV = GetReal(theHiV);
loV = GetReal(theLoV);
stepV = GetReal(theStepV);
curVal = valSave = val = GetReal(theValue);
theReadout = GetVar(theSlider, READOUT);
tracking = !GetPredicate(theSlider, TRACKNOT) && !(flags & F_OPTIONDOWN);
style = GetInt(theStyle);
if (style == SCALE || style == REVSCALE)
{
ObjPtr valArray, scale;
real *p;
if (scale = GetVar(theSlider, THESCALE))
{
valArray = GetVar(scale, VALUE);
p = ELEMENTS(valArray);
lilStep = p[2]/p[3];
}
else
{
theLilStep = GetRealVar("TrackSlider", theSlider, LILSTEP);
if (theLilStep) lilStep = GetReal(theLilStep);
else lilStep = 0;
}
}
if (right - left > top - bottom)
{
/* horizontal orientation */
if (style == SCROLL)
{
int wid = top - bottom;
/* which part is mouse in? */
if (mouseX > left && mouseX < left + wid) /* decr button */
{
/* follow mouse */
while (Mouse(&mX, &mY))
{
if (mX < left - SLOP || mX > left + wid + SLOP
|| mY < bottom - SLOP || mY > top + SLOP)
{
/* outside slop rect */
if (!hilit) continue;
SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
DrawMe(theSlider);
hilit = false;
}
else if (times(&tbuf) - prevTime > DELAY*HEARTBEAT)
{
/* decrement val by stepV */
prevTime = times(&tbuf);
if ((val -= stepV) < loV) val = loV;
if (!hilit || val != curVal)
{
SetVar(theSlider, VALUE, NewReal(val));
SetVar(theSlider, HIGHLIGHTED, NewInt(DECRHL));
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val;
hilit = true;
}
}
}
}
else if (mouseX < right && mouseX > right - wid) /* incr button */
{
/* follow mouse */
while (Mouse(&mX, &mY))
{
if (mX < right - wid - SLOP || mX > right + SLOP
|| mY < bottom - SLOP || mY > top + SLOP)
{
/* outside slop rect */
if (!hilit) continue;
SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
DrawMe(theSlider);
hilit = false;
}
else if (times(&tbuf) - prevTime > DELAY*HEARTBEAT)
{
/* increment val by stepV */
prevTime = times(&tbuf);
if ((val += stepV) > hiV) val = hiV;
if (!hilit || val != curVal)
{
SetVar(theSlider, VALUE, NewReal(val));
SetVar(theSlider, HIGHLIGHTED, NewInt(INCRHL));
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val;
hilit = true;
}
}
}
}
else /* track or thumb */
{
ObjPtr thePorSh;
real porSh, loC, hiC, siz, posn;
thePorSh = GetRealVar("TrackSlider", theSlider, PORTIONSHOWN);
if (thePorSh) porSh = GetReal(thePorSh);
else return ObjTrue; /* Yow! Oh, well. */
/* normalize portion shown */
porSh = porSh/(porSh + hiV - loV);
loC = left + wid + EDGE + SB_GAP;
hiC = right - wid - EDGE - SB_GAP;
siz = porSh*(hiC - loC);
if (siz < wid) siz = wid; /* min size */
hiC -= siz; /* max posn of thumb */
if (hiV <= loV) posn = loC;
else posn = (hiC - loC)*(val - loV)/(hiV - loV) + loC;
if (mouseX < posn || mouseX > posn + siz) /* in track */
{
/* jump thumb to click position, then follow */
offset = -siz/2;
if (hiC <= loC)
{
val = loV;
}
else
{
val = loV + (hiV - loV)*(mouseY + offset - loC)/(hiC - loC);
}
if (val < loV) val = loV;
else if (val > hiV) val = hiV;
SetVar(theSlider, VALUE, NewReal(curVal = val));
}
else offset = posn - mouseX;
SetVar(theSlider, HIGHLIGHTED, NewInt(THUMBHL));
DrawMe(theSlider);
/* now follow mouse with thumb */
while (Mouse(&mX, &mY))
{
if (mX < left + wid - SLOP || mX > right - wid + SLOP
|| mY < bottom - SLOP || mY > top + SLOP)
{
/* outside slop rect */
if (hilit)
{
SetVar(theSlider, VALUE, theValue);
SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val = valSave;
hilit = false;
}
if (!Mouse(&mX, &mY)) break;
}
else
{
/* follow with thumb */
if (hiC <= loC)
{
val = loV;
}
else
{
val = loV + (hiV - loV)*(mX + offset - loC)/(hiC - loC);
}
if (val < loV) val = loV;
else if (val > hiV) val = hiV;
if (!hilit || val != curVal) /* value has changed */
{
SetVar(theSlider, VALUE, NewReal(val));
SetVar(theSlider, HIGHLIGHTED, NewInt(THUMBHL));
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val; /* remember current value */
hilit = true;
}
}
}
}
}
else /* not a scrollbar */
{
if (style == SCALE || style == REVSCALE) /* adjust bounds */
{
left += HSCALEINSET - CTL_WID/2;
right -= HSCALEINSET - CTL_WID/2;
}
cp = ((val-loV)/(hiV - loV))*(right - left - CTL_WID)
+ left + CTL_WID/2;
if (mouseX < cp - CTL_WID/2 - 1 || mouseX > cp + CTL_WID/2 + 1)
{
/* click in track; jump control to click position */
offset = 0;
val = loV + (hiV - loV)*
(mouseX - left - CTL_WID/2)/(right - left - CTL_WID);
if (val < loV) val = loV;
else if (val > hiV) val = hiV;
else if (stepV != 0.0)
{
int n;
n = 0.5 + (val - loV)/stepV;
val = loV + n*stepV;
}
if (flags & F_CONSTRAIN && (style == SCALE || style == REVSCALE)
&& lilStep != 0)
{
/* constrain value to little steps of scale */
int n;
n = 0.5 + val/lilStep;
val = n*lilStep;
}
SetVar(theSlider, VALUE, NewReal(curVal = val));
}
else offset = cp - mouseX;
/* now follow the mouse */
while (Mouse(&mX, &mY))
{
if (mX < left - SLOP || mX > right + SLOP
|| mY < bottom - SLOP || mY > top + SLOP)
{
/* outside slop rect */
if (hilit)
{
SetVar(theSlider, VALUE, theValue);
SetVar(theSlider, HIGHLIGHTED, NewInt(false));
Update(theReadout, valSave);
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val = valSave;
hilit = false;
}
if (!Mouse(&mX, &mY)) break;
}
else
{
/* follow mouse with slider */
val = loV + (hiV - loV)*
(mX + offset - left - CTL_WID/2)/(right - left - CTL_WID);
if (val < loV) val = loV;
else if (val > hiV) val = hiV;
else if (stepV != 0.0)
{
int n;
n = 0.5 + val/stepV;
val = n*stepV;
}
else if (flags & F_CONSTRAIN &&
(style == SCALE || style == REVSCALE) && lilStep != 0)
{
/* constrain value to little steps of scale */
int n;
n = 0.5 + val/lilStep;
val = n*lilStep;
}
if (!hilit || val != curVal)
{
SetVar(theSlider, VALUE, NewReal(val));
SetVar(theSlider, HIGHLIGHTED, NewInt(true));
Update(theReadout, val);
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val;
hilit = true;
}
}
}
}
}
else
{
/* vertical orientation */
if (style == SCROLL)
{
int wid = right - left;
/* which part is mouse in? */
if (mouseY > bottom && mouseY < bottom + wid) /* decr button */
{
/* track mouse */
while (Mouse(&mX, &mY))
{
if (mX < left - SLOP || mX > right + SLOP
|| mY < bottom - SLOP || mY > bottom + wid + SLOP)
{
/* outside slop rect */
if (!hilit) continue;
SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
DrawMe(theSlider);
hilit = false;
}
else if (times(&tbuf) - prevTime > DELAY*HEARTBEAT)
{
/* decrement val by stepV */
prevTime = times(&tbuf);
if ((val -= stepV) < loV) val = loV;
if (!hilit || val != curVal)
{
SetVar(theSlider, VALUE, NewReal(val));
SetVar(theSlider, HIGHLIGHTED, NewInt(DECRHL));
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val;
hilit = true;
}
}
}
}
else if (mouseY < top && mouseY > top-wid) /* incr button */
{
/* track mouse */
while (Mouse(&mX, &mY))
{
if (mX < left - SLOP || mX > right + SLOP
|| mY < top - wid - SLOP || mY > top + SLOP)
{
/* outside slop rect */
if (!hilit) continue;
SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
DrawMe(theSlider);
hilit = false;
}
else if (times(&tbuf) - prevTime > DELAY*HEARTBEAT)
{
/* increment val by stepV */
prevTime = times(&tbuf);
if ((val += stepV) > hiV) val = hiV;
if (!hilit || val != curVal)
{
SetVar(theSlider, VALUE, NewReal(val));
SetVar(theSlider, HIGHLIGHTED, NewInt(INCRHL));
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val;
hilit = true;
}
}
}
}
else /* in thumb or track */
{
ObjPtr thePorSh;
real porSh, loC, hiC, siz, posn;
thePorSh = GetRealVar("TrackSlider", theSlider, PORTIONSHOWN);
if (thePorSh) porSh = GetReal(thePorSh);
else return ObjTrue; /* Yow! Oh, well. */
loC = bottom + wid + EDGE + SB_GAP;
hiC = top - wid - EDGE - SB_GAP;
/* normalize portion shown */
porSh = porSh/(porSh + hiV - loV);
siz = (hiC - loC)*porSh; /* size of thumb */
if (siz < wid) siz = wid; /* minimum size */
if (siz > hiC - loC) siz = hiC-loC; /* maximum size */
hiC -= siz; /* upper limit of posn */
if (hiV <= loV) posn = loC;
else posn = (hiC - loC)*(val - loV)/(hiV - loV) + loC;
if (mouseY < posn || mouseY > posn + siz) /* in track */
{
/* jump thumb to click position */
offset = -siz/2;
if (hiC <= loC)
{
val = loV;
}
else
{
val = loV + (hiV - loV)*(mouseY + offset - loC)/(hiC - loC);
}
if (val < loV) val = loV;
else if (val > hiV) val = hiV;
SetVar(theSlider, VALUE, NewReal(curVal = val));
}
else offset = posn - mouseY;
SetVar(theSlider, HIGHLIGHTED, NewInt(THUMBHL));
DrawMe(theSlider);
/* now follow mouse with thumb */
while (Mouse(&mX, &mY))
{
if (mX < left - SLOP || mX > right + SLOP
|| mY < bottom + wid - SLOP || mY > top - wid + SLOP)
{
/* outside slop rect */
if (hilit)
{
SetVar(theSlider, VALUE, theValue);
SetVar(theSlider, HIGHLIGHTED, NewInt(0x00));
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val = valSave;
hilit = false;
}
if (!Mouse(&mX, &mY)) break;
}
else
{
/* track mouse with thumb */
if (hiC <= loC)
{
val = loV;
}
else
{
val = loV + (hiV - loV)*(mY + offset - loC)/(hiC - loC);
}
if (val < loV) val = loV;
else if (val > hiV) val = hiV;
if (!hilit || val != curVal)
{
SetVar(theSlider, VALUE, NewReal(val));
SetVar(theSlider, HIGHLIGHTED, NewInt(THUMBHL));
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val;
hilit = true;
}
}
}
}
}
else /* not a scrollbar */
{
if (style == SCALE || style == REVSCALE) /* adjust bounds */
{
bottom += VSCALEINSET - CTL_WID/2;
top -= VSCALEINSET - CTL_WID/2;
}
cp = ((val - loV)/(hiV - loV))*(top - bottom - CTL_WID)
+ bottom + CTL_WID/2 + 0.5;
if (mouseY < cp - CTL_WID/2 - 1 || mouseY > cp + CTL_WID/2 + 1)
{
/* click in track; jump control to click position */
offset = 0;
val = loV + (hiV - loV)*
(mouseY - bottom - CTL_WID/2)/(top - bottom - CTL_WID);
if (val < loV) val = loV;
else if (val > hiV) val = hiV;
else if (stepV != 0.0)
{
int n;
n = 0.5 + (val - loV)/stepV;
val = loV + n*stepV;
}
if (flags & F_CONSTRAIN && (style == SCALE || style == REVSCALE)
&& lilStep != 0)
{
/* constrain value to little steps of scale */
int n;
n = 0.5 + val/lilStep;
val = n*lilStep;
}
SetVar(theSlider, VALUE, NewReal(curVal = val));
}
else offset = cp - mouseY;
/* now follow the mouse */
while (Mouse(&mX, &mY))
{
if (mX < left - SLOP || mX > right + SLOP
|| mY < bottom - SLOP || mY > top + SLOP)
{
/* outside slop rect */
if (hilit)
{
SetVar(theSlider, VALUE, theValue);
SetVar(theSlider, HIGHLIGHTED, NewInt(false));
Update(theReadout, valSave);
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val = valSave;
hilit = false;
}
if (!Mouse(&mX, &mY)) break;
}
else
{
/* follow mouse with slider */
val = loV + (hiV - loV)*
(mY + offset - bottom - CTL_WID/2)/(top - bottom - CTL_WID);
if (val < loV) val = loV;
else if (val > hiV) val = hiV;
else if (stepV != 0.0)
{
int n;
n = 0.5 + (val - loV)/stepV;
val = loV + n*stepV;
}
else if (flags & F_CONSTRAIN &&
(style == SCALE || style == REVSCALE) && lilStep != 0)
{
/* constrain value to little steps of scale */
int n;
n = 0.5 + val/lilStep;
val = n*lilStep;
}
if (!hilit || val != curVal)
{
SetVar(theSlider, VALUE, NewReal(val));
SetVar(theSlider, HIGHLIGHTED, NewInt(true));
Update(theReadout, val);
DrawMe(theSlider);
if (tracking) ChangedValue(theSlider);
curVal = val;
hilit = true;
}
}
}
}
}
SetVar(theSlider, HIGHLIGHTED, NewInt(false));
DrawMe(theSlider);
if (val != valSave) /* value has changed */
{
Update(theReadout, val);
ChangedValue(theSlider);
LogControl(theSlider);
}
#endif
return ObjTrue;
}